//
//  BasicFileIO.hpp
//  learnC++
//
//  Created by liuzhibing on 2018/7/10.
//  Copyright © 2018年 yunfan.com. All rights reserved.
//

#ifndef BasicFileIO_hpp
#define BasicFileIO_hpp

#include <stdio.h>
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <string>

//C ++中的文件I / O与普通I / O非常相似（有一些小的复杂性）。 C ++中有3个基本文件I / O类：ifstream（派生自istream），ofstream（派生自ostream）和fstream（派生自iostream）。 这些类分别进行文件输入，输出和输入/输出。 要使用文件I / O类，您需要包含fstream标头。

//与已经可以使用的cout，cin，cerr和clog流不同，文件流必须由程序员明确设置。 但是，这非常简单：打开一个文件进行读取和/或写入，只需实例化相应文件I / O类的对象，并将文件名作为参数。 然后使用insert（<<）或extract（>>）运算符来读/写文件。 完成后，有几种方法可以关闭文件：显式调用close（）函数，或者让文件I / O变量超出范围（文件I / O类析构函数将为您关闭文件）。
using namespace std;

class BasicFileIO {
    
    
public:
    BasicFileIO(){
        
    }
    ~BasicFileIO(){
        
    }
    
    void ofstreamTest(){
        
        //需要点击Edit scheme -> option -> work direct -> custom ->文件图标才能写文件
        //创建相同文件，会覆盖前面的文件
        // ofstream is used for writing files
        // We'll make a file called Sample.dat
        std::ofstream outf("sample2.txt");
        
        // If we couldn't open the output file stream for writing
        if (!outf) {
            
            cerr << "Uh oh,Sample.dat could not be opened for writing!" << endl;
            exit(1);
            
        }
        
        // We'll write two lines into this file
        outf << "This is line 1" << endl;
        outf << "This is line 2" << endl;
        
        // When outf goes out of scope, the ofstream
        // destructor will close the file
        //或显式调用
        outf.close();
        
    }
    
    void appendFile(){
        // We'll pass the ios:app flag to tell the ofstream to append
        // rather than rewrite the file.  We do not need to pass in ios::out
        // because ofstream defaults to ios::out
        ofstream outf("Sample2.txt", ios::app);
        
        // If we couldn't open the output file stream for writing
        if (!outf)
        {
            // Print an error and exit
            cerr << "Uh oh, Sample.dat could not be opened for writing!" << endl;
            exit(1);
        }
        
        outf << "This is line 3" << endl;
        outf << "This is line 4" << endl;
        
        outf.close();
        
        //也可以显式打开文件
        outf.open("Sample2.txt",ios::app);
        if (!outf)
        {
            // Print an error and exit
            cerr << "Uh oh, Sample.dat could not be opened for writing!" << endl;
            exit(1);
        }
        outf << "This is line 5" << endl;
        
        outf.close();
    }
    
//    请注意，如果我们已到达文件末尾（EOF），ifstream将返回0
    
    void ifstreamTest(){
        // ifstream is used for reading files
        // We'll read from a file called Sample.dat
        ifstream inf("sample2.txt");
        
        // If we couldn't open the output file stream for reading
        if (!inf) {
            //error
            cerr << "Uh oh, Sample.dat could not be opened for reading!" << endl;
            exit(1);
        }
        
        // While there's still stuff left to read
        while (inf) {
            // read stuff from the file into a string and print it
            std::string strInput;
//            inf >> strInput;//读取整行
            getline(inf, strInput);
            
            cout << strInput << endl;
        }
        
        inf.close();
    }
    
    
};
/*
 
 
 output在C++中可能被缓存。这意味着输出到文件流的任何内容都可能无法立即写入磁盘。相反，可以对几个输出操作进行批处理和一起处理。这主要是出于性能原因。将缓冲区写入磁盘时，这称为刷新缓冲区。导致缓冲区刷新的一种方法是关闭文件 - 缓冲区的内容将刷新到磁盘，然后文件将被关闭。
 
 但在某些情况下，它可能导致不警惕的并发症。在这种情况下，主要的罪魁祸首是缓冲区中有数据，然后程序立即终止（通过崩溃或通过调用exit（））。在这些情况下，不执行文件流类的析构函数，这意味着文件永远不会关闭，这意味着永远不会刷新缓冲区。在这种情况下，缓冲区中的数据不会写入磁盘，并且会永久丢失。这就是为什么在调用exit（）之前显式关闭任何打开的文件总是一个好主意。
 
 可以使用ostream :: flush（）函数手动刷新缓冲区或将std :: flush发送到输出流。这些方法中的任何一个都可以用于确保缓冲区的内容立即写入磁盘，以防程序崩溃。
 
 一个有趣的注意事项是std :: endl;还会刷新输出流。因此，过度使用std :: endl（导致不必要的缓冲区刷新）会在执行缓冲I / O时产生性能影响，其中刷新是昂贵的（例如写入文件）。出于这个原因，具有性能意识的程序员通常会使用'\ n'而不是std :: endl在输出流中插入换行符，以避免不必要的缓冲区刷新。
 
 文件模式
 
 如果我们尝试写入已存在的文件会发生什么？ 再次运行输出示例显示每次运行程序时都会完全覆盖原始文件。 相反，如果我们想在文件的末尾添加更多数据呢？ 事实证明，文件流构造函数采用可选的第二个参数，允许您指定有关如何打开文件的信息。 此参数称为模式，它接受的有效标志位于Ios类中。
 
 模式    含义
 app    Opens the file in append mode
 ate    Seeks to the end of the file before reading/writing
 binary    Opens the file in binary mode (instead of text mode)
 in    Opens the file in read mode (default for ifstream)
 out    Opens the file in write mode (default for ofstream)
 trunc    Erases the file if it already exists
 
 可以通过将它们按位OR运算来指定多个标志（使用|运算符）。 Ifstream默认为ios :: in file模式。 Ofstream默认为ios :: out文件模式。 并且fstream默认为ios :: in | ios :: out文件模式，意味着您可以默认读取和写入。
 
 
 */



#endif /* BasicFileIO_hpp */
